/**
 * Created by IntelliJ IDEA.
 * User: Administrator
 * Date: Dec 31, 2009
 * Time: 10:53:55 AM
 * To change this template use File | Settings | File Templates.
 */
import dk.brics.automaton.Automaton;
import java.util.List;
import java.util.Set;
import org.jdom.Element;

// Referenced classes of package dk.brics.dsd:
//            Regexp, Reference, RegexpDefinition, InternalSchemaErrorException,
//            Context, Validator, Schema

class ReferenceRegexp extends Regexp
{

    ReferenceRegexp(Element element, Schema schema)
    {
        ref = new Reference(element, schema);
    }

    RegexpDefinition resolve(Context context)
    {
        Definition definition = ref.resolve();
        if(!(definition instanceof RegexpDefinition))
            throw new InternalSchemaErrorException();
        else
            return (RegexpDefinition)definition;
    }

    public Element toXML(Context context)
    {
        if(context.containsDef(ref.ref))
        {
            return new Element("union", "http://www.brics.dk/DSD/2.0");
        } else
        {
            RegexpDefinition regexpdefinition = resolve(context);
            Element element = new Element(regexpdefinition.contenttype ? "contenttype" : "stringtype", "http://www.brics.dk/DSD/2.0");
            element.setAttribute("ref", ref.orig_ref);
            return element;
        }
    }

    boolean match(String s, Context context)
    {
        if(context.containsDef(ref.ref))
        {
            return false;
        } else
        {
            RegexpDefinition regexpdefinition = resolve(context);
            context.enterDef(ref.ref);
            boolean flag = regexpdefinition.exp.match(s, context);
            context.leaveDef(ref.ref);
            return flag;
        }
    }

    Automaton toAutomaton(Context context)
    {
        if(this.automaton != null)
            return this.automaton;
        if(context.containsDef(ref.ref))
            return Automaton.makeEmpty();
        Automaton automaton;
        if(ref.ref.equals("http://www.brics.dk/DSD/character-classes:EXTENDER"))
            automaton = getExtender();
        else
        if(ref.ref.equals("http://www.brics.dk/DSD/character-classes:COMBININGCHAR"))
            automaton = getCombiningchar();
        else
        if(ref.ref.equals("http://www.brics.dk/DSD/character-classes:DIGIT"))
            automaton = getDigit();
        else
        if(ref.ref.equals("http://www.brics.dk/DSD/character-classes:NCNAMECHAR"))
            automaton = getNcnamechar();
        else
        if(ref.ref.equals("http://www.brics.dk/DSD/character-classes:IDEOGRAPHIC"))
            automaton = getIdeographic();
        else
        if(ref.ref.equals("http://www.brics.dk/DSD/character-classes:BASECHAR"))
            automaton = getBasechar();
        else
        if(ref.ref.equals("http://www.brics.dk/DSD/character-classes:NAMECHAR"))
            automaton = getNamechar();
        else
        if(ref.ref.equals("http://www.brics.dk/DSD/character-classes:LETTER"))
            automaton = getLetter();
        else
        if(ref.ref.equals("http://www.brics.dk/DSD/2.0:NCNAME"))
            automaton = getNcname();
        else
        if(ref.ref.equals("http://www.brics.dk/DSD/2.0:QNAME"))
            automaton = getQname();
        else
        if(ref.ref.equals("http://www.brics.dk/DSD/2.0:PNAME"))
        {
            automaton = getPname();
        } else
        {
            RegexpDefinition regexpdefinition = resolve(context);
            context.enterDef(ref.ref);
            automaton = regexpdefinition.exp.toAutomaton(context);
            context.leaveDef(ref.ref);
            Validator.debug("created automaton for " + ref.ref);
        }
        this.automaton = automaton;
        return automaton;
    }

    boolean isChar(Context context)
    {
        if(context.containsDef(ref.ref))
        {
            return false;
        } else
        {
            RegexpDefinition regexpdefinition = resolve(context);
            context.enterDef(ref.ref);
            boolean flag = regexpdefinition.exp.isChar(context);
            context.leaveDef(ref.ref);
            return flag;
        }
    }

    void addBoolexps(Context context, Set set)
    {
        if(context.containsDef(ref.ref))
        {
            return;
        } else
        {
            RegexpDefinition regexpdefinition = resolve(context);
            context.enterDef(ref.ref);
            set.addAll(regexpdefinition.exp.getBoolexps(context));
            context.leaveDef(ref.ref);
            return;
        }
    }

    void getMentioned(Context context, Set set, List list)
    {
        if(context.containsDef(ref.ref))
        {
            return;
        } else
        {
            RegexpDefinition regexpdefinition = resolve(context);
            context.enterDef(ref.ref);
            regexpdefinition.exp.getMentioned(context, set, list);
            context.leaveDef(ref.ref);
            return;
        }
    }

    boolean checkRepeatUnion(Context context)
    {
        if(context.containsDef(ref.ref))
        {
            return false;
        } else
        {
            RegexpDefinition regexpdefinition = resolve(context);
            context.enterDef(ref.ref);
            boolean flag = regexpdefinition.exp.isRepeatUnion(context);
            context.leaveDef(ref.ref);
            return flag;
        }
    }

    boolean checkUnion(Context context)
    {
        if(context.containsDef(ref.ref))
        {
            return false;
        } else
        {
            RegexpDefinition regexpdefinition = resolve(context);
            context.enterDef(ref.ref);
            boolean flag = regexpdefinition.exp.checkUnion(context);
            context.leaveDef(ref.ref);
            return flag;
        }
    }

    boolean checkSimple(Context context)
    {
        if(context.containsDef(ref.ref))
        {
            return false;
        } else
        {
            RegexpDefinition regexpdefinition = resolve(context);
            context.enterDef(ref.ref);
            boolean flag = regexpdefinition.exp.checkSimple(context);
            context.leaveDef(ref.ref);
            return flag;
        }
    }

    Reference ref;
}
